package com.google.code.memoriesalbum.controller.oauth;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slim3.controller.Controller;
import org.slim3.controller.Navigation;
import org.slim3.datastore.Datastore;
import org.slim3.datastore.EntityNotFoundRuntimeException;

import com.google.appengine.api.datastore.Key;
import com.google.code.memoriesalbum.model.Account;
import com.google.code.memoriesalbum.util.Constants;
import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthException;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;

/**
 * GoogleのPicasa,Calendarサービスへのアクセスを許可するページへリダイレクトさせる。
 * @author shin1ogawa
 */
public class IndexController extends Controller {

	static final Logger logger = Logger.getLogger(IndexController.class.getName());


	@Override
	protected Navigation run() {
		try {
			if (StringUtils.isEmpty(asString("token"))) {
				return randomToken();
			} else {
				return redirect();
			}
		} catch (IOException e) {
			throw new RuntimeException(e);
		} catch (OAuthException e) {
			throw new RuntimeException(e);
		}
	}

	private Navigation randomToken() throws IOException {
		String randomUUID = null;
		boolean alreadyExists = true;
		do {
			randomUUID = UUID.randomUUID().toString();
			Key key = Datastore.createKey(Account.class, randomUUID);
			try {
				Datastore.get(key);
			} catch (EntityNotFoundRuntimeException e) {
				alreadyExists = false;
			}
		} while (alreadyExists);
		response.setContentType("text/plain");
		response.setCharacterEncoding("utf-8");
		response.getWriter().println(randomUUID);
		response.flushBuffer();
		return null;
	}

	private Navigation redirect() throws IOException, OAuthException {
		GoogleOAuthParameters params = new GoogleOAuthParameters();
		params.setOAuthConsumerKey(Constants.CONSUMER_KEY);
		params.setOAuthConsumerSecret(Constants.CONSUMER_SECRET);
		params.setOAuthSignatureMethod("HMAC-SHA1");
		params.setScope("http://picasaweb.google.com/data/ http://www.google.com/calendar/feeds/");

		GoogleOAuthHelper helper = new GoogleOAuthHelper(new OAuthHmacSha1Signer());
		try {
			helper.getUnauthorizedRequestToken(params);
		} catch (OAuthException e) {
			logger.log(Level.WARNING, "リクエストトークンの取得に失敗しました。", e);
			response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
			throw e;
		}
		StringBuilder callBackUrl = new StringBuilder(request.getRequestURL());
		callBackUrl.append("save?secret=").append(
				URLEncoder.encode(params.getOAuthTokenSecret(), "UTF-8"));
		if (StringUtils.isNotEmpty(request.getQueryString())) {
			callBackUrl.append("&").append(request.getQueryString());
		}
		logger.info("callbackurl=" + callBackUrl.toString());
		params.setOAuthCallback(callBackUrl.toString());
		String authorizationUrl = helper.createUserAuthorizationUrl(params);
		logger.info("authorizationUrl=" + authorizationUrl);
		return new Navigation(authorizationUrl, true);
	}
}
